#include "SSM.hpp"
/*
 theta1 rho
 theta2 sigma1
 theta3 sigma2
 theta4 d
 
 */
class StoVol : public  SSM
{

	public:
	StoVol(double *Y, mat X,int T) : SSM(Y,X,T){
		_d= new boost::math::normal_distribution<>(0,1);
	       mat m(1,1);
	       mat Sigma(1,1);
	       m.fill(0);
	       Sigma.fill(1);
	       int p=1;
		_N=new Distribution::Gaussian(p,m,Sigma);	
		_T=T;
	}
	
	inline mat rq(mat theta, mat Xt, int M)
	{
		mat S(1,1);
		mat m(1,1);
		mat X(M,1);
	//	cout << theta(0,0);
		for(int i=0;i<M;i++)
		{
			m(0,0)=theta(0,0)*Xt(i,0);
			S(0,0)=theta(1,0);
			_N->Set_s(S);
			_N->Set_m(m);
			X(i,span::all)=_N->r(1);
		}
		return X;		
	}
	inline double dq(mat Xt, mat theta,double Y, mat Xt1)
	{
		mat S(1,1);
		mat m(1,1);
		m(0,0)=theta(0,0)*Xt1(0,0);
		S(0,0)=theta(1,0);

		_N->Set_s(S);
		_N->Set_m(m);
		return log(_N->d(Xt));
	}

	inline double dg(mat Xt, mat theta,double Y, mat Xt1)
	{
		mat S(1,1);
		mat m(1,1);
		m(0,0)=theta(0,0)*Xt1(0,0);
		S(0,0)=theta(1,0);

		_N->Set_s(S);
		_N->Set_m(m);
		return log(_N->d(Xt));
	}
	inline double df(double Y,mat Xt, mat theta)
	{
		mat S(1,1);
		mat m(1,1);
		S(0,0)=exp(Xt(0,0))*theta(3,0);
		m(0,0)=theta(2,0);

		_N->Set_s(S);
		_N->Set_m(m);
		mat Yt(1,1);
		Yt(0,0)=Y;
		return log(_N->d(Yt));
	}
	inline	mat rm(mat theta){
		mat S(1,1);
		mat m(1,1);
		m(0,0)=0;
		S(0,0)=theta(1,0)/(1-theta(0,0)*theta(0,0));

		_N->Set_s(S);
		_N->Set_m(m);
		return _N->r(1);
	}
	int Get_p(void){return 1; }
	int Constraints( mat theta)
	{
		int res=0;
		if(theta(0,0)>1 |theta(0,0)<-1)
		{
			res=1;
		}else if(theta(0,1)<0 | theta(0,2)<0 | theta(0,3)<0)
		{
			res=1;
		}
		return res;


	}	
	int Get_T(void)
	{
		return _T;
	}
	private:
		boost::math::normal_distribution<> *_d;
		Distribution::Gaussian *_N;
		int _T;
};
